package com.ruoyi.vplat.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSONArray;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.vplat.websocket.handler.WebsocketMsgHandler18;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.websocket.handler.AbstractWebsocketMsgHandler;
import com.ruoyi.common.websocket.server.WebSocketUtils;
import com.ruoyi.vplat.domain.VplatDevice;
import com.ruoyi.vplat.mapper.VplatDeviceMapper;
import com.ruoyi.vplat.service.IVplatVideoService;

/**
 * 设备Service业务层处理
 *
 * @author ruoyi
 * @date 2024-04-29
 */
@Service
@Slf4j
public class VplatVideoServiceImpl implements IVplatVideoService {
    @Autowired
    private VplatDeviceMapper vplatDeviceMapper;

    @Override
    public JSONObject playVideo(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        String accessType = device.getProtocol();
        String gatewayId = device.getGatewayId();
        String clientId = (String) param.get("clientId");
        Integer clientType = (Integer) param.get("protocol");
        Integer videoFlag = (Integer) param.get("videoFlag");
        Integer seqNum = (Integer) param.get("seqNum");
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }
        int num = Integer.parseInt(seqNum.toString());
        JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("2105", new HashMap<String, Object>() {{
            put("protocol", clientType == null ? 0 : clientType);
            put("seqNum", num);
            put("clientId", clientId);
            put("devId", deviceNo);
            put("videoFlag", videoFlag != null ? videoFlag : 1);
        }});
        //String gateway = getGateway(accessType, gatewayId);
        JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
        return result;
    }

    private JSONObject error(String deviceNo, String errorMsg) {
        return new JSONObject() {{
            put("param", new JSONObject() {{
                put("szDevId", deviceNo);
                put("iMessageCode", -1);
                put("szMessageString", errorMsg);
            }});
        }};
    }

    @Override
    public JSONObject closeVideo(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        String accessType = device.getProtocol();
        String gatewayId = device.getGatewayId();
        String clientId = (String) param.get("clientId");
        Integer clientType = (Integer) param.get("protocol");
        Integer seqNum = (Integer) param.get("seqNum");
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }
        int num = Integer.parseInt(seqNum.toString());

        JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("2108", new HashMap<String, Object>() {{
            put("protocol", clientType == null ? 0 : clientType);
            put("seqNum", num);
            put("clientId", clientId);
            put("devId", deviceNo);
        }});
        //String gateway = getGateway(accessType, gatewayId);
        JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
        return result;
    }

    @Override
    public JSONObject startHistoryRecord(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        String accessType = device.getProtocol();
        String gatewayId = device.getGatewayId();
        String clientId = (String) param.get("clientId");
        Integer clientType = (Integer) param.get("protocol");
        String startTime = (String) param.get("startTime");
        String endTime = (String) param.get("endTime");
        String clientIp = (String) param.get("clientIp");
        Integer seqNum = (Integer) param.get("seqNum");
        if (StringUtils.isBlank(startTime)) {
            return error(deviceNo, "开始时间不能为空");
        }
        String datePattern = "yyyy-MM-dd HH:mm:ss";
        try {
            DateUtils.parseDate(startTime, datePattern);
        } catch (ParseException e) {
            return error(deviceNo, "开始时间格式必须为" + datePattern);
        }

        if (StringUtils.isBlank(endTime)) {
            return error(deviceNo, "结束时间不能为空");
        }
        try {
            DateUtils.parseDate(endTime, datePattern);
        } catch (ParseException e) {
            return error(deviceNo, "结束时间格式必须为" + datePattern);
        }
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }
        int num = Integer.parseInt(seqNum.toString());
        JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("10040", new HashMap<String, Object>() {{
            put("protocol", clientType == null ? 0 : clientType);
            put("seqNum", num);
            put("clientId", clientId);
            put("devId", deviceNo);
            put("startTime", startTime);
            put("endTime", endTime);
            put("clientIp", clientIp);
        }});
        //String gateway = getGateway(accessType, gatewayId);
        log.info("向网关请求回话录像:\n{}", commandTemplate);
        JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
        return result;
    }

    @Override
    public JSONObject stopHistoryRecord(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        String accessType = device.getProtocol();
        String gatewayId = device.getGatewayId();
        Integer clientId = (Integer) param.get("clientId");
        String clientType = (String) param.get("protocol");
        Integer seqNum = (Integer) param.get("seqNum");
        Integer playId = (Integer) param.get("playId");
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }
        int num = Integer.parseInt(seqNum.toString());
        JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("10055", new HashMap<String, Object>() {{
            put("protocol", StringUtils.isBlank(clientType) ? 0 : clientType);
            put("seqNum", num);
            put("clientId", clientId);
            put("devId", deviceNo);
            put("playId", playId);
        }});
        //String gateway = getGateway(accessType, gatewayId);
        log.info("向网关请求停止回放录像:\n{}", commandTemplate);
        JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
        return result;
    }

//	private static String getGateway(String accessType, String gatewayId) {
//		String gateway = null;
//		if(accessType.equals("2")) {
//			gateway = "GB-" + gatewayId;
//		}else {
//			gateway = "ACS-" + gatewayId;
//		}
//		return gateway;
//	}

    @Override
    public JSONObject startRecord(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        String accessType = device.getProtocol();
        String gatewayId = device.getGatewayId();
        String clientId = (String) param.get("clientId");
        Boolean blocking = (Boolean) param.get("blocking");
//		String clientType = (String) param.get("protocol");
//		Integer videoFlag = (Integer) param.get("videoFlag");
        Integer capture = (Integer) param.get("capture");
        Integer record = (Integer) param.get("record");
        Integer recordDuration = (Integer) param.get("recordDuration");
        String type = (String) param.get("type");
        Integer seqNum = (Integer) param.get("seqNum");
        if (capture == null || capture == null || recordDuration == null) {
            return error(deviceNo, "抓拍/录像参数不能为空");
        }
        if (capture.intValue() == 0 && record.intValue() == 0) {
            return error(deviceNo, "开始抓拍/录像参数不合理");
        }
        if (capture.intValue() < 0 || capture.intValue() > 1) {
            return error(deviceNo, "抓拍参数必须在0/1之间");
        }
        if (record.intValue() < 0 || record.intValue() > 1) {
            return error(deviceNo, "录像参数必须在0/1之间");
        }
        if (recordDuration == null) {
            recordDuration = 10;
        }
        if (recordDuration.intValue() < 0 || recordDuration.intValue() > 1800) {
            return error(deviceNo, "录像时长必须在0-1800秒之间");
        }
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }

        int num = Integer.parseInt(seqNum.toString());
        int recordTime = recordDuration.intValue();
        int protocol = 3;
        JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("17", new HashMap<String, Object>() {{
            put("protocol", protocol);
            put("seqNum", num);
            put("clientId", clientId);
            put("devId", deviceNo);
            put("devName", device.getName());
            put("capture", capture);
            put("record", record);
            put("recordDuration", recordTime);
            put("type", StringUtils.isBlank(type) ? "alarm" : type);
        }});
        int index = gatewayId.indexOf("-");
        gatewayId = "RS-" + gatewayId.substring(index + 1);
        log.info("向网关{}请求开始抓拍/录像:\n{}", gatewayId, commandTemplate);
        // 网关第一次响应结果
        JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
        if (blocking == null || blocking.booleanValue() == false) {
            return result;
        } else {//如果阻塞响应,则返回网关第二次响应结果
            JSONObject command = result.getJSONObject("command");
            String szClientId = command.getString("szClientId");
            Integer iSeqNum = command.getInteger("iSeqNum");
            String key = szClientId + "_" + iSeqNum;
            CountDownLatch countDownLatch = new CountDownLatch(1);
            WebsocketMsgHandler18.commands.put(key, countDownLatch);
            int waitTIme = recordDuration.intValue();
            try {
                countDownLatch.await(waitTIme + 120, TimeUnit.SECONDS);
                synchronized (key.intern()) {
                    Object obj = WebsocketMsgHandler18.commands.get(key);
                    WebsocketMsgHandler18.commands.remove(key);
                    if (obj instanceof JSONObject) {
                        return (JSONObject) obj;
                    } else {
                        return error(deviceNo, "抓拍/录像响应超时");
                    }

                }
            } catch (InterruptedException e) {
                //e.printStackTrace();
                synchronized (key.intern()) {
                    WebsocketMsgHandler18.commands.remove(key);
                    return error(deviceNo, "抓拍/录像响应超时");
                }
            }
        }

    }

    @Override
    public JSONObject stopRecord(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        String accessType = device.getProtocol();
        String gatewayId = device.getGatewayId();
        String clientId = (String) param.get("clientId");
        Integer seqNum = (Integer) param.get("seqNum");
        //Integer iVideoFlag = (Integer) param.get("iVideoFlag");
        Integer recId = (Integer) param.get("recId");
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }
        int num = Integer.parseInt(seqNum.toString());
        int protocol = 3;
        JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("19", new HashMap<String, Object>() {{
            put("protocol", protocol);
            put("seqNum", num);
            put("clientId", clientId);
            put("devId", deviceNo);
            put("recId", recId);
        }});
        int index = gatewayId.indexOf("-");
        gatewayId = "RS-" + gatewayId.substring(index + 1);
        log.info("向网关{}请求停止抓拍/录像:\n{}", gatewayId, commandTemplate);
        JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
        return result;
    }

    @Override
    public JSONObject control(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        //String accessType = device.getProtocol();
        String gatewayId = device.getGatewayId();
        String clientId = (String) param.get("clientId");
        //Integer clientType = (Integer) param.get("protocol");
        //Integer videoFlag = (Integer) param.get("videoFlag");
        Integer seqNum = (Integer) param.get("seqNum");
        Integer light = (Integer) param.get("light");
        Integer wiper = (Integer) param.get("wiper");
        Integer fan = (Integer) param.get("fan");
        Integer zoom = (Integer) param.get("zoom");
        Integer tilt = (Integer) param.get("tilt");
        Integer pan = (Integer) param.get("pan");
        Integer focus = (Integer) param.get("focus");
        Integer iris = (Integer) param.get("iris");
        Integer speed = (Integer) param.get("speed");
        Integer stop = (Integer) param.get("stop");
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }
        int num = Integer.parseInt(seqNum.toString());
        if (light != null) {// 控制灯光
            return null;
        } else if (wiper != null) {// 控制雨刷
            return null;
        } else if (fan != null) {// 控制风扇
            return null;
        } else {// 控制云台
            JSONObject error = checkControlParams(zoom, tilt, pan, focus, iris, speed, stop, deviceNo);
            if (error != null) return error;

            JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("1097", new HashMap<String, Object>() {{
                //put("protocol", clientType == null ? 0 : clientType);
                put("protocol", 0);
                put("seqNum", num);
                put("clientId", clientId);
                put("devId", deviceNo);
                put("zoom", zoom);
                put("tilt", tilt);
                put("pan", pan);
                put("focus", focus);
                put("iris", iris);
                put("speed", speed);
                put("stop", stop);
            }});
            //String gateway = getGateway(accessType, gatewayId);
            JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
            log.info("向网关{}请求云台控制:\n{}", gatewayId, commandTemplate);
            return result;
        }


    }

    private JSONObject checkControlParams(Integer zoom, Integer tilt, Integer pan, Integer focus, Integer iris, Integer speed, Integer stop, String deviceNo) {
        if (zoom == null || tilt == null || pan == null || focus == null || iris == null || speed == null || stop == null) {
            return error(deviceNo, "云台控制参数不能为空");
        }
        JSONObject error = checkParams1(deviceNo, zoom, tilt, pan, focus, iris);
        if (error != null) return error;
        int speedValue = speed.intValue();
        if(speedValue < 0 || speedValue > 255){
            return error(deviceNo, "云台控制参数错误");
        }
        int stopValue = stop.intValue();
        if(stopValue != 0 && stopValue != 1){
            return error(deviceNo, "云台控制参数错误");
        }
        return null;
    }

    private JSONObject checkParams1(String deviceNo, Integer... params) {
        if (params != null) {
            for (Integer param : params) {
                int value = param.intValue();
                if (value != 0 && value != 1 && value != 2) {
                    return error(deviceNo, "云台控制参数错误");
                }
            }
        }
        return null;
    }

    public JSONObject getPTZ(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        //String accessType = device.getProtocol();
        String gatewayId = device.getGatewayId();
        String clientId = (String) param.get("clientId");
        //Integer clientType = (Integer) param.get("protocol");
        //Integer videoFlag = (Integer) param.get("videoFlag");
        Integer seqNum = (Integer) param.get("seqNum");
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }
        int num = Integer.parseInt(seqNum.toString());
        JSONArray devList = new JSONArray();
        devList.add(new JSONObject(){{
            put("szDevId", deviceNo);
        }});
        JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("10044", new HashMap<String, Object>() {{
            //put("protocol", clientType == null ? 0 : clientType)
            put("protocol", 6);
            put("seqNum", num);
            put("clientId", clientId);
            put("devList", devList);
        }});
        //String gateway = getGateway(accessType, gatewayId);
        JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
        log.info("向网关{}请求获取球机PTZ值:\n{}", gatewayId, commandTemplate);
        return result;


    }
    /**
     * 设置球机PTZ值
     * @param param
     * @return
     */
    @Override
    public JSONObject setPTZ(Map<String, Object> param) {
        String deviceNo = (String) param.get("deviceNo");
        VplatDevice device = vplatDeviceMapper.selectById(deviceNo);
        if (device == null) {
            return error(deviceNo, "设备不存在");
        }
        String gatewayId = device.getGatewayId();
        String clientId = (String) param.get("clientId");
        Double pan = null;
        Double tilt = null;
        Double zoom = null;
        try {
            pan = param.get("pan") != null ? Double.parseDouble(param.get("pan").toString()) : null;
            tilt = param.get("tilt") != null ? Double.parseDouble(param.get("tilt").toString()) : null;
            zoom = param.get("zoom") != null ? Double.parseDouble(param.get("zoom").toString()) :  null;
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return error(deviceNo, "参数解析异常");
        }
        if (pan == null || tilt == null || zoom == null) {
            return error(deviceNo, "云台控制参数不能为空");
        }
        if (pan < 0 || pan > 360 || tilt < 0 || tilt > 360 || zoom < 0) {
            return error(deviceNo, "云台控制参数错误");
        }
        double p = pan.doubleValue();
        double t = tilt.doubleValue();
        double v = zoom.doubleValue();

        Integer seqNum = (Integer) param.get("seqNum");
        if (seqNum == null) {
            seqNum = AbstractWebsocketMsgHandler.getRandomNum(7);
        }
        int num = Integer.parseInt(seqNum.toString());
        JSONObject commandTemplate = AbstractWebsocketMsgHandler.getCommandTemplate("10046", new HashMap<String, Object>() {{
            put("protocol", 6);
            put("seqNum", num);
            put("clientId", clientId);
            put("devId", deviceNo);
            put("pan", p);
            put("tilt", t);
            put("zoom", v);
        }});
        //String gateway = getGateway(accessType, gatewayId);
        JSONObject result = WebSocketUtils.sendSyncMessage(gatewayId, commandTemplate);
        log.info("向网关{}请求设置球机PTZ值:\n{}", gatewayId, commandTemplate);
        return result;
    }
}
